﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class WrlImporter : MonoBehaviour {


    public List<WrlEntity> wrls = new List<WrlEntity>(); //wrl对象列表
    public string path;                                 //导出路径                      
    public  GameObject newObject;           //带有meshFilter 和 meshRenderer组件的空预制体


    private List<Vector3> vertices = new List<Vector3>();
    private List<Vector3> normals = new List<Vector3>();
    private List<int> triangles = new List<int>();
    private Color diffuseColor;     //材质颜色




   
    // Use this for initialization
    void Start () {
        WrlHelper wrlhelper = new WrlHelper();
        string msg="";
        wrls = wrlhelper.ReadWrl(@path, ref msg);
        if (wrls==null)
        {
            Debug.Log("解析失败,原因:"+msg);
            return;
        }
        GameObject father = null;
        RecursiveDrawMesh(father,wrls);
       
    }
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.A))
        {
         
            foreach (WrlEntity w in wrls)
            {
                GameObject g = GameObject.Find(w.name);
                GenImportModel(g);
                ForeachChild(w.childs);
                ///ForeachChild(w.childs;
            }
        }
    }
    public void ForeachChild(List<WrlEntity> childs)
    {
        foreach (WrlEntity w in childs)
        {
            GameObject g = GameObject.Find(w.name);
            GenImportModel(g);
            ForeachChild(w.childs);
        }
    }
        

    public void GenImportModel(GameObject g)
    {
        float minX = 1000.0f;
        float maxX = -1000.0f;
        float minY = 1000.0f;
        float maxY = -1000.0f;
        float minZ = 1000.0f;
        float maxZ = -1000.0f;
       
        Mesh mesh = g.GetComponent<MeshFilter>().mesh;
        List<Vector3> vertexList = mesh.vertices.ToList<Vector3>();
        List<int> triangleList = mesh.triangles.ToList<int>();
        mesh = new Mesh();
        for (int i = 0; i < vertexList.Count; i++)
        {
            if (minX > vertexList[i].x)
                minX = vertexList[i].x;
            if (minY > vertexList[i].y)
                minY = vertexList[i].y;
            if (minZ > vertexList[i].z)
                minZ = vertexList[i].z;
            if (maxX < vertexList[i].x)
                maxX = vertexList[i].x;
            if (maxY < vertexList[i].y)
                maxY = vertexList[i].y;
            if (maxZ < vertexList[i].z)
                maxZ = vertexList[i].z;

        }
        for (int i = 0; i < vertexList.Count; i++)
        {
            vertexList[i] = new Vector3(vertexList[i].x - minX,
                                        vertexList[i].y - minY,
                                        vertexList[i].z - minZ);
        }
        g.transform.position = g.transform.position+ g.transform.forward* minZ+g.transform.up*minY+g.transform.right*minX;
        foreach(Transform child in g.transform)
        {
            child.position = child.position - g.transform.forward * minZ - g.transform.up * minY - g.transform.right * minX;
        }
        mesh.vertices = vertexList.ToArray();
        mesh.triangles = triangleList.ToArray();
        mesh.RecalculateNormals();
        g.GetComponent<MeshFilter>().mesh = mesh;
        Debug.Log(new Vector3(minX, minY, minZ));
        

    }
    /// <summary>
    /// 将分割shape得到的顶点，三角型索引，颜色等读出并填充到数组
    /// </summary>
    /// <param name="wrl">单个wrl对象</param>
    void ReadWrlEntity(WrlEntity wrl)
    {
        float xScale = wrl.scale.x , yScale = wrl.scale.y, zScale = wrl.scale.z ;
        if (wrl.parentEntity != null)
        {
            xScale = wrl.scale.x * wrl.parentEntity.scale.x;
            yScale = wrl.scale.y * wrl.parentEntity.scale.y;
            zScale = wrl.scale.z * wrl.parentEntity.scale.z;
        }
        if (wrl.diffuseColorInfo != "")
        {
            var diffuseColorInfo = wrl.diffuseColorInfo.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
            diffuseColor = new Color(float.Parse(diffuseColorInfo[1]), float.Parse(diffuseColorInfo[2]),float.Parse(diffuseColorInfo[3]),1f);
        }
        if (wrl.trianglesInfo != "")
        {
            var tempString = wrl.trianglesInfo.Replace("coordIndex ", string.Empty).Replace(" ", string.Empty)
                .Replace("-1,", string.Empty).Replace(",-1",string.Empty);
            var trianglesInfo = tempString.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
            for (int j = 0; j < trianglesInfo.Length; j++)
                triangles.Add( int.Parse(trianglesInfo[j]));
        }
        if (wrl.vertexsInfo != "")
        {
            var tempString = wrl.vertexsInfo.Replace("point ", string.Empty); 
            var verticesInfo = tempString.Split(", ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
            var firstVisitList = new List<bool>();
            for (int i = 0; i < verticesInfo.Length / 3; i++)
            {
                vertices.Add(new Vector3(float.Parse(verticesInfo[i * 3])*xScale, yScale*float.Parse(verticesInfo[i * 3 + 1]),
                   zScale* float.Parse(verticesInfo[i * 3 + 2])));
                firstVisitList.Add(false);
            }
            if (verticesInfo.Length / 3 != triangles.Count)
            {
                for (int i = 0; i < verticesInfo.Length / 3; i++)
                {
                    for (int j = 0; j < triangles.Count; j++)
                    {
                        if (triangles[j] == i && firstVisitList[i] == false)
                        {
                            firstVisitList[i] = true;
                            continue;
                        }
                        else if (triangles[j] == i && firstVisitList[i] == true)
                            vertices.Add(new Vector3(xScale*float.Parse(verticesInfo[i * 3]), yScale* float.Parse(verticesInfo[i * 3 + 1]),
                             zScale*   float.Parse(verticesInfo[i * 3 + 2])));
                    }
                }
                int maxTriangle = verticesInfo.Length / 3 - 1;
                for (int i = 0; i < verticesInfo.Length / 3; i++)
                { 
                    for (int j = 0; j < triangles.Count; j++)
                    {
                        if (triangles[j] == i && firstVisitList[i] == true)
                        {
                            firstVisitList[i] = false;
                            continue;
                        }
                        else if (triangles[j] == i && firstVisitList[i] == false)
                            triangles[j] = maxTriangle = maxTriangle + 1;
                    }
                }
            }
        }
    }


    /// <summary>
    /// 递归遍历wrl对象列表，并调用画模型，调轴心，填充数组 这些方法
    /// </summary>
    /// <param name="father">保存上一次得到的父物体</param>
    /// <param name="wrlList">wrl对象列表</param>
    void RecursiveDrawMesh(GameObject father,List<WrlEntity> wrlList)
    {
        GameObject tempfather = father;
        for (int i = 0; i < wrlList.Count; i++)
        {
        
            ReadWrlEntity(wrlList[i]);
            GameObject tempObject = null;

            if (tempfather != null)
            {
                tempObject = GameObject.Instantiate(newObject, Vector3.zero, Quaternion.identity);
                tempObject.name = wrlList[i].name;
                DrawMesh(wrlList[i], tempObject);
                tempObject.transform.SetParent(tempfather.transform);
                tempObject.transform.localPosition = wrlList[i].translation;
                //ChangePivot(tempObject);
                tempObject.transform.localRotation = Quaternion.Euler(wrlList[i].rotation);
            }
            else
            {
                tempObject = GameObject.Instantiate(newObject, Vector3.zero, Quaternion.identity);
                tempObject.name = wrlList[i].name;
                DrawMesh(wrlList[i], tempObject);
                tempfather = tempObject;
                tempObject.transform.position = wrlList[i].translation;
                //ChangePivot(tempObject);
                tempObject.transform.rotation = Quaternion.Euler(wrlList[i].rotation);
            }
            if (wrlList[i].childs.Count != 0)
            {
                tempfather = tempObject;
                RecursiveDrawMesh(tempfather,wrlList[i].childs);
            }
            tempfather = father;
        }
    }



    /// <summary>
    ///  画网格
    /// </summary>
    /// <param name="wrl">单个wrl对象</param>
    /// <param name="tempObj">单个物体</param>
    void DrawMesh(WrlEntity wrl,GameObject tempObj)
    {
        MeshRenderer childMeshRenderer = tempObj.GetComponent<MeshRenderer>();
        MeshFilter childMeshFilter = tempObj.GetComponent<MeshFilter>();
        Mesh childMesh = new Mesh();
      
        if(vertices.Count!=0)
        childMesh.vertices = vertices.ToArray();
        if (triangles.Count != 0)
        {
            childMesh.triangles = triangles.ToArray();
           childMesh.RecalculateNormals();
            childMesh.RecalculateTangents();
        }
        childMeshFilter.mesh = childMesh;
        if (wrl.diffuseColorInfo != "")
            childMeshRenderer.material.color = diffuseColor;
        vertices.Clear();
        triangles.Clear();

    }


    /// <summary>
    ///  调轴心
    /// </summary>
    /// <param name="g">单个物体</param>
    public void ChangePivot(GameObject g)
    {
        float minX = 1000.0f;
        float maxX = -1000.0f;
        float minY = 1000.0f;
        float maxY = -1000.0f;
        float minZ = 1000.0f;
        float maxZ = -1000.0f;
        Mesh mesh = g.GetComponent<MeshFilter>().mesh;
        List<Vector3> vertexList = mesh.vertices.ToList<Vector3>();
        List<int> triangleList = mesh.triangles.ToList<int>();
        mesh = new Mesh();
        for (int i = 0; i < vertexList.Count; i++)
        {
            if (minX > vertexList[i].x)
                minX = vertexList[i].x;
            if (minY > vertexList[i].y)
                minY = vertexList[i].y;
            if (minZ > vertexList[i].z)
                minZ = vertexList[i].z;
            if (maxX < vertexList[i].x)
                maxX = vertexList[i].x;
            if (maxY < vertexList[i].y)
                maxY = vertexList[i].y;
            if (maxZ < vertexList[i].z)
                maxZ = vertexList[i].z;

        }
        for (int i = 0; i < vertexList.Count; i++)
        {
            vertexList[i] = new Vector3(vertexList[i].x - minX,
                                        vertexList[i].y - minY,
                                        vertexList[i].z - minZ);
        }
        mesh.vertices = vertexList.ToArray();
        mesh.triangles = triangleList.ToArray();
        mesh.RecalculateNormals();
        g.GetComponent<MeshFilter>().mesh = mesh;
        g.transform.position += new Vector3(minX, minY, minZ);
    }
}
